package com.xmh.reptile.main;

import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlTextInput;
import com.xmh.myutil.othertest.HtmlUtil;
import com.xmh.reptile.dao.SexVideoDAO;
import com.xmh.reptile.entity.SexVideoEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;

//@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration("/spring_bean.xml")
//@Transactional
@Slf4j
public class SexReptile {

    @Autowired
    private SexVideoDAO dao;

    @Autowired
    private ThreadPoolTaskExecutor poolTaskExecutor;

    private final ExecutorService executorService = Executors.newCachedThreadPool();

    final WebClient webClient = new WebClient(BrowserVersion.CHROME);// 新建一个模拟谷歌Chrome浏览器的浏览器客户端对象

    @Test
    public void main() throws IOException, InterruptedException {

        webClient.getOptions().setThrowExceptionOnScriptError(false);// 当JS执行出错的时候是否抛出异常, 这里选择不需要
        webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);// 当HTTP的状态非200时是否抛出异常, 这里选择不需要
        webClient.getOptions().setActiveXNative(false);
        webClient.getOptions().setCssEnabled(false);// 是否启用CSS, 因为不需要展现页面, 所以不需要启用
        webClient.getOptions().setJavaScriptEnabled(true); // 很重要，启用JS
        webClient.setJavaScriptEngine(new MyJavaScriptEngine(webClient));// 自定义JavaScript引擎，有js错误不打印
        webClient.setAjaxController(new NicelyResynchronizingAjaxController());// 很重要，设置支持AJAX

        try {
            webClient.getPage("https://sssjj3.com/video/detail/230613?ccc=3yyyuu.com");
        } catch (Exception e) {
            e.printStackTrace();
        }

        webClient.waitForBackgroundJavaScript(3000);// 异步JS执行需要耗时,所以这里线程要阻塞30秒,等待异步JS执行结束

        String homeUrl = "https://sssjj3.com/video/monthly-ranking?page=";

        for (int i = 1; i <= 8; i++) {
            String url = homeUrl + i;

            Document document = Jsoup.connect(url).get();

            Iterator<Element> iterator = document.select("div[class='pure-u-1 thumbnail'] > a[target='_blank']")
                    .iterator();
            while (iterator.hasNext()) {
                Element element = iterator.next();
                String attr = element.attr("href");

                String substringBetween = StringUtils.substringBetween(attr, "detail/", "#");

                String urlString = "https://sssjj3.com/video/detail/" + substringBetween + "#header";

                HtmlPage page = webClient.getPage(urlString);

                long timeoutMillis = 3000L;

                webClient.waitForBackgroundJavaScript(timeoutMillis);// 异步JS执行需要耗时,所以这里线程要阻塞30秒,等待异步JS执行结束

                String pageXml = page.asXml();

                if (!pageXml.contains("var video = document.getElementById('video');")) {
                    HtmlForm form = page.getForms().get(0);
                    HtmlTextInput txtUName = (HtmlTextInput) form.getInputByName("c1"); //
                    txtUName.setValueAttribute("0118659813");

                    HtmlTextInput txtPwd = (HtmlTextInput) form.getInputByName("c2");// 密码框
                    txtPwd.setValueAttribute("1908282238");

                    form.getButtonByName("").click();

                    webClient.waitForBackgroundJavaScript(timeoutMillis);// 等待1秒

                    page = webClient.getPage(urlString);

                    webClient.waitForBackgroundJavaScript(timeoutMillis);// 异步JS执行需要耗时,所以这里线程要阻塞30秒,等待异步JS执行结束

                    pageXml = page.asXml();
                }
                String downId = StringUtils.substringBetween(pageXml, "hls.loadSource(\"/cdn/vip/hls/", ".");

                String lodTiele = Jsoup.parse(pageXml).getElementById("title").text();

                String title = lodTiele.replace("/", "_").replace(" ", "_");

                poolTaskExecutor.execute(() -> {
                    Future<String> future = executorService.submit(() -> {
                        downloadZip(downId, lodTiele);
                        return "sueecs";
                    });
                    try {
                        // 设置超时时间
                        future.get(60L * 60L * 3L, TimeUnit.SECONDS);
                    } catch (Exception e) {
                        future.cancel(true);

                        log.error("");
                        log.error("====================== 下载超时 ==========================");
                        log.error("标题：" + title);
                        log.error("", e);
                        log.error("");

                        String pathname = "I:\\download\\" + title;
                        String downloadUrl = "https://sssjj3.com/cdn/xx/file/" + downId + "/";

                        new File(pathname).delete();

                        SexVideoEntity entity = new SexVideoEntity();
                        entity.setTitle(title);
                        entity.setPath(pathname);
                        entity.setUrl(downloadUrl);
                        Integer valueOf = Integer.valueOf(downId);
                        entity.setDownid(valueOf);
                        entity.setState(false);
                        dao.add(entity);
                    }
                });

                Thread.sleep(timeoutMillis);
            }
        }
        Thread.sleep(1000L * 60L * 60L * 24L * 3L);
    }

    private void downloadZip(String downId, String lodTiele) {
        String title = lodTiele.replace("/", "_").replace(" ", "_");

//		String downloadUrl = getDownloadUrl(lodTiele, downId);
        String downloadUrl = "https://sssjj3.com/cdn/xx/file/" + downId + "/";

        String pathname = "I:\\download\\" + title;

        SexVideoEntity entity = new SexVideoEntity();
        entity.setTitle(title);
        entity.setPath(pathname);
        entity.setUrl(downloadUrl);
        Integer valueOf = Integer.valueOf(downId);
        entity.setDownid(valueOf);

        SexVideoEntity sexVideoEntity = dao.get(new SexVideoEntity(valueOf));
        if (sexVideoEntity != null) {
            if (sexVideoEntity.getState()) {
                log.info("====================== 已存在==========================");
                return;
            }
            dao.delete(sexVideoEntity);
        }
        System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2,SSLv3");
        log.info("");
        log.info("====================== 下载开始==========================");
        log.info("标题：" + title);
        log.info("地址：" + downloadUrl);
        log.info("");
        File file = new File(pathname);
        FileOutputStream fileOutputStream = null;
        InputStream inputStream = null;
        try {
            fileOutputStream = new FileOutputStream(file);

            URL url = new URL(downloadUrl);

            URLConnection connection = url.openConnection();

            inputStream = connection.getInputStream();

            int length = 0;
            byte[] bytes = new byte[1024];
            while ((length = inputStream.read(bytes)) != -1) {
                fileOutputStream.write(bytes, 0, length);
            }
            fileOutputStream.close();
            inputStream.close();

            entity.setState(true);
            dao.add(entity);
            log.info("");
            log.info("======================下载完成==========================");
            log.info("标题：" + title);
            log.info("");
        } catch (IOException e) {
            entity.setState(false);
            dao.add(entity);
            log.error("======================下载报错==========================");
            log.error("标题：" + title);
            log.error("地址：" + downloadUrl);
            log.error("", e);
            try {
                if (fileOutputStream != null) {
                    fileOutputStream.close();
                }
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException e1) {
                log.error("", e1);
            }
            file.delete();
        }
    }

    public String getDownloadUrl(String title, String downId) {
        try {
            String titleEncode = URLEncoder.encode(title, "utf8").replace("+", "%20");

            int x = 15;
            int y = 6;

            return "https://x" + x + "y" + y + ".qq360cn.com/xx/file/" + downId + "/" + titleEncode;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }

    public int getRandom(int min, int max) {
        Random ra = new Random();
        int x = ra.nextInt(max + 1 - min) + min;
        return x;
    }

    private void page(String url) {
        final WebClient webClient = new WebClient(BrowserVersion.CHROME);// 新建一个模拟谷歌Chrome浏览器的浏览器客户端对象

        webClient.getOptions().setThrowExceptionOnScriptError(false);// 当JS执行出错的时候是否抛出异常, 这里选择不需要
        webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);// 当HTTP的状态非200时是否抛出异常, 这里选择不需要
        webClient.getOptions().setActiveXNative(false);
        webClient.getOptions().setCssEnabled(false);// 是否启用CSS, 因为不需要展现页面, 所以不需要启用
        webClient.getOptions().setJavaScriptEnabled(true); // 很重要，启用JS
        webClient.setAjaxController(new NicelyResynchronizingAjaxController());// 很重要，设置支持AJAX

        HtmlPage page = null;
        try {
            page = webClient.getPage("http://ent.sina.com.cn/film/");// 尝试加载上面图片例子给出的网页
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            webClient.close();
        }

        webClient.waitForBackgroundJavaScript(30000);// 异步JS执行需要耗时,所以这里线程要阻塞30秒,等待异步JS执行结束

        String pageXml = page.asXml();// 直接将加载完成的页面转换成xml格式的字符串

        // TODO 下面的代码就是对字符串的操作了,常规的爬虫操作,用到了比较好用的Jsoup库

        Document document = Jsoup.parse(pageXml);// 获取html文档
        List<Element> infoListEle = document.getElementById("feedCardContent").getElementsByAttributeValue("class",
                "feed-card-item");// 获取元素节点等
        infoListEle.forEach(element -> {
            System.out.println(element.getElementsByTag("h2").first().getElementsByTag("a").text());
            System.out.println(element.getElementsByTag("h2").first().getElementsByTag("a").attr("href"));
        });
    }

    @Test
    public void test2() throws IOException, InterruptedException {
        poolTaskExecutor.execute(() -> {
            System.out.println("1");
            String url = "http://localhost:8080/userPayController/selectList?amnout=9";

            String doGet = HtmlUtil.doGet(url);

            System.out.println("2");
            System.out.println(doGet);
        });

//		ExecutorService executor = Executors.newSingleThreadExecutor();
//		Callable<Result> work = new Callable<Result>() {
//		    @Override
//		    public Result call() {
//		        // do something
//		        return  result
//		    }
//		};
//		Future<Result> future = executor.submit(work);
//		try {
//		    result = future.get(TIMEOUT, TIMEUNIT); 
//		} catch (TimeoutException e) { 
//		    ...
//		} catch (...) {
//		    ...
//		}

        Thread.sleep(10000);
    }

    @Test
    public void test3() throws InterruptedException {
        try {
            runWithTimeout(() -> {
                while (true)
                    System.out.println("运行中············");
            }, 1, TimeUnit.SECONDS);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("结束1");
        Thread.sleep(2000L);
        System.out.println("结束2");
    }

    public void runWithTimeout(final Runnable runnable, long timeout, TimeUnit timeUnit) throws Exception {
        runWithTimeout(() -> {
            runnable.run();
            return null;
        }, timeout, timeUnit);
    }

    public <T> T runWithTimeout(Callable<T> callable, long timeout, TimeUnit timeUnit) throws Exception {
//		final ExecutorService executor = Executors.newSingleThreadExecutor();
//		final Future<T> future = executor.submit(callable);
        Future<T> future = poolTaskExecutor.submit(callable);
        try {
            return future.get(timeout, timeUnit);
        } catch (Exception e) {
            future.cancel(true);
            throw e;
        }
    }

    @Test
    public void test4() {
        List<SexVideoEntity> selectList = dao.selectList(new HashMap<String, Object>());

        for (SexVideoEntity sexVideoEntity : selectList) {
            File file = new File(sexVideoEntity.getPath());

            File newName = new File("I:\\共享文件夹\\SexVideo\\" + sexVideoEntity.getTitle());

            file.renameTo(newName);
        }

    }

    @Test
    public void test5() throws UnsupportedEncodingException {
        String string = "jux00634 家庭乱伦 親父の女 本田岬.mp4";

        String urlString = "https://x2y3.qq360cn.com/xx/file/887373/" + string;

//		String encode = System.out.println(encode);
    }

}
